#include "WiFiConfig.h"
#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLEAdvertising.h>

TaskHandle_t wifiMonitorTask = NULL;  // 全局变量，保存任务句柄
void WiFiConfig::connectToWiFi(char *ssid, char *password) {
  WiFi.setSleep(true);                 // 启用WiFi轻睡眠（重要！）
  WiFi.setTxPower(WIFI_POWER_8_5dBm);  // 降低发射功率
  // 设置 WiFi 为 STA 模式
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(1000);
  if (ssid == nullptr) {
    WiFi.begin();  // 连接已保存的wifi
  } else {
    WiFi.begin(ssid, password);  // 连接新的wifi
  }

  if (wifiMonitorTask == NULL) {
    // 启动异步线程，监听wifi连接状态
    xTaskCreatePinnedToCore(
      _wifiMonitor,      // 任务函数
      "WiFiMonitor",     // 任务名称
      4096,              // 堆栈大小（字节）
      this,              // 传递给任务的参数
      1,                 // 任务优先级（1 是低优先级）
      &wifiMonitorTask,  // 任务句柄
      0);                // 运行在核心0上
  }
}

// 使用异步线程，监听wifi连接状态
void WiFiConfig::_wifiMonitor(void *pvParameters) {
  while (true) {
    if (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(".");
    } else {
      setCpuFrequencyMhz(80);  // 连接后降频CPU，ESP32默认240MHz，降至80MHz
      Serial.printf("WiFi连接正常，IP地址: %s\n", WiFi.localIP().toString().c_str());
    }
    vTaskDelay(10000 / portTICK_PERIOD_MS);  // 每10秒检查一次
  }
}

void WiFiConfig::startConfigPortal() {
  WiFi.softAP(apSSID, apPassword);   // 进入配网模式AP
  IPAddress myIP = WiFi.softAPIP();  // 获取AP模式IP
  // 将IP通过串口打印出来，方便调试
  Serial.print("AP模式下的IP地址: ");
  Serial.println(myIP);
  // 将IP通过蓝牙通信广播
  _advertiseIP(myIP);

  // 启动Web服务器,通过IP地址访问配置页面
  server.on("/", [this]() {
    _handleAPRoot();
  });  // 配网页面
  server.on("/save", [this]() {
    _handleAPSave();
  });  // 保存配网信息
  server.on("/gpio2", [this]() {
    _handleGPIO2();
  });  // 舵机控制页面
  server.on("/control", [this]() {
    _handleControlGPIO2();
  });  // 舵机控制处理
  server.begin();
}

void WiFiConfig::handleClient() {
  server.handleClient();
}
// 配网网页
void WiFiConfig::_handleAPRoot() {
  String html = R"=====(
  <!DOCTYPE html>
  <html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>设备配网</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container mt-5">
      <div class="card">
        <div class="card-header bg-primary text-white">
          <h4>WiFi配置</h4>
        </div>
        <div class="card-body">
          <form action="/save" method="POST">
            <div class="mb-3">
              <label for="ssid" class="form-label">WiFi名称</label>
              <input type="text" class="form-control" id="ssid" name="ssid" required>
            </div>
            <div class="mb-3">
              <label for="password" class="form-label">WiFi密码</label>
              <input type="password" class="form-control" id="password" name="password">
            </div>
            <button type="submit" class="btn btn-primary">保存配置</button>
          </form>
        </div>
      </div>
    </div>
  </body>
  </html>
  )=====";

  server.send(200, "text/html", html);
}

// 保存配网信息并尝试连接
void WiFiConfig::_handleAPSave() {
  String ssid = server.arg("ssid");
  String password = server.arg("password");

  server.send(200, "text/html", "配置保存成功,1秒后重新连接WiFi...");
  connectToWiFi((char *)ssid.c_str(), (char *)password.c_str());
}

// 通过BLE广播IP地址
void WiFiConfig::_advertiseIP(IPAddress ip) {
  BLEDevice::init("TouAP");

  String strIP = ip.toString();

  BLEAdvertisementData advertisementData;
  advertisementData.setManufacturerData(strIP);  // strIP 是你的字符串数据

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
}

// 控制舵机
void WiFiConfig::_handleGPIO2() {
  String html = "<!DOCTYPE html><html><head><meta charset='UTF-8'>";
  html += "<title>ESP32-C3-SuperMini舵机控制</title>";
  html += "<style>body{font-family:Arial;text-align:center;}";
  html += "button{padding:15px 25px;margin:10px;font-size:16px;}</style></head>";
  html += "<body><h1>ESP32-C3-SuperMini舵机控制</h1>";
  html += "<button onclick=\"controlServo(0)\">0度</button>";
  html += "<button onclick=\"controlServo(90)\">90度</button>";
  html += "<button onclick=\"controlServo(180)\">180度</button>";
  html += "<script>";
  html += "function controlServo(angle){";
  html += "  fetch('/control?angle='+angle).then(r=>r.text());";
  html += "}";
  html += "</script></body></html>";

  server.send(200, "text/html", html);
}

void WiFiConfig::_handleControlGPIO2() {
    Serial.println("收到舵机控制请求");
  if (server.hasArg("angle")) {
    int angle = server.arg("angle").toInt();
    if (angleCallback != nullptr) {
        Serial.println("企图发送舵机控制请求");
      angleCallback(angle);
    }
    server.send(200, "text/plain", "角度设置为: " + String(angle) + "度");
  } else {
    server.send(400, "text/plain", "参数错误");
  }
}